<script lang="ts" setup>
import {
  reactive,
  onMounted,
  defineProps,
  defineEmits,
  defineExpose
} from 'vue'

declare const uni: any // 使用 uni.showModal 做删除确认，避免依赖不存在的组件

interface FetchResult<T = any> {
  items: T[]
  hasMore?: boolean
}

const props = defineProps({
  fetcher: {
    type: Function as unknown as () => (p: any) => Promise<FetchResult>,
    required: false
  },
  items: { type: Array as unknown as () => any[], default: () => [] },
  pageSize: { type: Number, default: 20 },
  emptyText: { type: String, default: '暂无数据' }
})

const emit = defineEmits<{
  (e: 'add'): void
  (e: 'edit', row: any): void
  (e: 'delete', row: any): void
  (e: 'query', filters: Record<string, any>): void
}>()

const state = reactive({
  loading: false,
  refreshing: false,
  page: 1,
  hasMore: true,
  data: [] as any[],
  filters: {} as Record<string, any>
})

const load = async (opts: { reset?: boolean } = {}) => {
  if (state.loading) return
  if (opts.reset) {
    state.page = 1
    state.hasMore = true
    state.data = []
  }
  if (!state.hasMore) return

  state.loading = true
  try {
    if (props.fetcher) {
      const res = await props.fetcher({
        page: state.page,
        size: props.pageSize,
        filters: state.filters
      })
      if (state.page === 1) state.data = res.items
      else state.data = state.data.concat(res.items)
      state.hasMore = res.hasMore ?? res.items.length >= props.pageSize
      state.page++
    } else {
      if (state.page === 1) {
        state.data = props.items.slice()
      }
      state.hasMore = false
    }
  } finally {
    state.loading = false
    state.refreshing = false
  }
}

const refresh = async () => {
  state.refreshing = true
  await load({ reset: true })
}

const applyFilters = async (f: Record<string, any>) => {
  state.filters = { ...f }
  emit('query', state.filters)
  await load({ reset: true })
}

const loadMore = async () => {
  if (!state.hasMore || state.loading) return
  await load()
}

const confirmDelete = (row: any) => {
  uni.showModal({
    title: '删除',
    content: '确定删除该条记录吗？',
    success: (res: any) => {
      if (res.confirm) {
        emit('delete', row)
      }
    }
  })
}

onMounted(() => {
  load({ reset: true })
})

defineExpose({ refresh, loadMore, state })
</script>

<template>
  <wd-card class="p-3 rounded-2xl bg-white">
    <!-- 顶部：筛选 + 操作 -->
    <view class="flex items-center gap-3 mb-3">
      <view class="flex-1">
        <slot name="filters">
          <view class="flex items-center gap-2">
            <wd-input
              v-model:value="state.filters.keyword"
              placeholder="搜索关键词"
              clearable
              class="flex-1"
            />
            <wd-button
              type="primary"
              size="small"
              @click="applyFilters(state.filters)"
              >搜索</wd-button
            >
            <wd-button
              size="small"
              type="warning"
              plain
              @click="
                () => {
                  state.filters = {}
                  applyFilters({})
                }
              "
              >重置</wd-button
            >
          </view>
        </slot>
      </view>

      <view class="flex items-center gap-2">
        <slot name="actions">
          <wd-button type="success" size="small" @click="emit('add')"
            >+ 新增</wd-button
          >
        </slot>
      </view>
    </view>

    <!-- 内容区域：表单（可选）、列表 -->
    <view class="space-y-3">
      <slot name="form" />

      <view class="grid grid-cols-1 gap-3">
        <view
          v-if="state.loading && state.page === 1"
          class="py-8 flex justify-center items-center"
          >加载中...</view
        >

        <template v-if="state.data.length">
          <view
            v-for="(row, idx) in state.data"
            :key="row.id ?? idx"
            class="p-3 rounded-xl bg-gradient-to-br from-white to-gray-50 shadow-sm border border-solid border-transparent hover:border-gray-200 transition"
          >
            <slot name="item" :row="row" :index="idx">
              <view class="flex items-start justify-between">
                <view class="flex-1">
                  <view class="text-base font-medium truncate">{{
                    row.title || row.name || '未命名'
                  }}</view>
                  <view class="text-sm text-muted mt-1 truncate">{{
                    row.desc || row.subtitle || ''
                  }}</view>
                </view>

                <view class="flex items-center gap-2 ml-3">
                  <wd-button size="mini" plain @click="emit('edit', row)"
                    >编辑</wd-button
                  >
                  <wd-button
                    size="mini"
                    type="danger"
                    plain
                    @click="confirmDelete(row)"
                    >删除</wd-button
                  >
                </view>
              </view>
            </slot>
          </view>
        </template>

        <view v-else-if="!state.loading" class="py-12 text-center text-muted">{{
          emptyText
        }}</view>

        <view v-if="state.loading && state.page > 1" class="py-4 text-center"
          >加载更多...</view
        >
        <view
          v-if="!state.hasMore && state.data.length"
          class="py-3 text-center text-sm text-muted"
          >—— 到底了 ——</view
        >
      </view>
    </view>
  </wd-card>
</template>

<style scoped>
.wd-card:hover {
  transform: translateY(-2px);
}
</style>
